package com.itcam.interview.pro00.thread;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author : Cammy.Wu
 * Description : 
 */

public class ReentrantLockExample {
    private final ReentrantLock lock = new ReentrantLock(); // 非公平锁
    private final Condition condition = lock.newCondition();
    private boolean resourceAvailable = false;

    public void accessResource() {
        // 尝试获取锁，等待 2 秒
        try {
            if (lock.tryLock(2, TimeUnit.SECONDS)) {
                try {
                    while (!resourceAvailable) {
                        try {
                            // 等待资源可用
                            condition.await();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + " 正在访问资源。");
                    // 模拟使用资源
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    System.out.println(Thread.currentThread().getName() + " 访问资源结束。");
                } finally {
                    lock.unlock();
                }
            } else {
                System.out.println(Thread.currentThread().getName() + " 未能获取到锁。");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    public void makeResourceAvailable() {
        lock.lock();
        try {
            resourceAvailable = true;
            System.out.println("资源已可用，通知等待的线程。");
            // 通知所有等待的线程
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockExample example = new ReentrantLockExample();
        // 创建并启动多个线程尝试访问资源
        for (int i = 0; i < 3; i++) {
            new Thread(() -> example.accessResource()).start();
        }
        // 模拟一段时间后资源可用
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        example.makeResourceAvailable();
    }
}
